
from fastapi import Path,HTTPException,Query,APIRouter,Depends,status,Header
from pydantic import BaseModel,Field
from typing import List
from datetime import datetime,timedelta
from fastapi.security import OAuth2PasswordBearer,OAuth2PasswordRequestForm
from passlib.context import CryptContext    #处理哈希密码
from jose import JWTError,jwt               #处理jwt token
from utils.response_code import resp_200,resp_400
from sql.db import yhb_crud,cpb_crud
# from sql.db import yhb_crud,cpb_crud,clb_crud

SECRET_KEY = 'test' #hash钥匙
ALGORITHM = 'HS256' #加密算法
ACCESS_TOKEN_EXPIRE_DAYS =  7  #token过期时间
#处理密码
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
#指定获取token的接口
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="user/token")

jianpiao_router = APIRouter()

class UserOut(BaseModel):
    yhbh:str
    yhxm:str
    yhzt:str
    czqx:str
    qsph:str
    zzph:str
    bfqs:str
    bfzz:str
    yhgs:str
    yhgroup:str

class UserIn(BaseModel):
    yhbh:str = Field(None)
    yhxm:str = Field(None)
    yhmm:str = Field(None)
    yhzt:str = Field(None)
    czqx:str = Field(None)
    qsph:str = Field(None)
    zzph:str = Field(None)
    bfqs:str = Field(None)
    bfzz:str = Field(None)
    yhgs:str = Field(None)
    yhgroup:str = Field(None)

class SearchIn(BaseModel):
    cpbh:str = Field(None)

class SearchOut(BaseModel):
    cpbh:str = Field(None)
    sfcz:str = Field(None)
    mdcz:str = Field(None)
    spy:str = Field(None)
    # pj:str = Field(None)
    # rqsj:str = Field(None)
    zwh:str = Field(None)
    cplx:str = Field(None)
    cpzt:str = Field(None)
    tgpy:str = Field(None)
    # sxf:str = Field(None)
    jpk:str = Field(None)
    sfjp:str = Field(None)
    bbkh:str = Field(None)
    spjs:str = Field(None)
    tgjs:str = Field(None)
    cljs:str = Field(None)
    # tbpj:str = Field(None)
    # spsj:str = Field(None)
    xlbh:str = Field(None)
    mdzh:str = Field(None)
    ssgs:str = Field(None)
    jpfs:str = Field(None)
    bcbh:str = Field(None)
    lkxm:str = Field(None)
    sfzh:str = Field(None)

class TicketIn(BaseModel):
    bbkh:str = Field(None)

class TicketOut(BaseModel):
    cpbh:str  #车票编号
    sfcz:str #始发车站
    mdcz:str #目的车站
    spy:str #售票员
    # pj:   #票价
    # rqsj:  #日期时间
    zwh:str #座位号
    cplx:str #车票类型
    cpzt:str #车票状态
    tgpy:str #退改票价
    # sxf:   #手续费
    jpk:str  #检票口
    sfjp:str #是否检票
    bbkh:str #报班卡号
    # spjs  #售票结算
    # tgjs #退改结算
    # cljs #车辆结算
    # tbpj #特别票价
    # spsj #售票结算
    xlbh:str  #线路编号
    # mdzh: #目的站号
    # ssgs: #所属公司
    # jpfs: #检票方式
    # bcbh:str  #班次编号
    # lkxm:str  #旅客姓名
    # sfzh:str #始发站号

class DayinbbkhIn(BaseModel):
    bbkh:str = Field(None)
 
#rqsj,zwh,cpbh,bbkh,mdcz,cplx,jpk,pj,cpzt,clb.cpzh,clb.czxm
class DayinbbkhOut(BaseModel):
    #rqsj:Time #cpb
    bbkh:str = Field(None)
    cpzh:str = Field(None)
    zwh:str = Field(None)
    cpbh:str = Field(None)
    mdcz:str = Field(None)
    cplx:str = Field(None)
    jpk:str = Field(None)
    #pj:str
    cpzt:str = Field(None)
    czxm:str = Field(None)

class TokenIn(BaseModel):
    yhbh:str = Field(None)
    yhmm:str = Field(None)

class Token(BaseModel):
    access_token:str
    token_type:str

#校验
def validateUser(id,password):
    user = yhb_crud.get_user(id)
    if not user:    #没有有找到user
        return None
    #验证密码
    if pwd_context.verify(password,user['yhmm']):  
        return user  #返回用户信息
    else:
        return None

#生成token
@jianpiao_router.post('/token',response_model=Token)
def token(userinfo:TokenIn):
    #进行用户名密码校验
    res = validateUser(int(userinfo.yhbh),userinfo.yhmm)
    if res == None:
        #失败响应，传递失败消息
        return resp_400(msg='用户名或密码错误')
    pay_load = {'yhbh':res['yhbh'],'yhxm':res['yhxm'],'czqx':res['czqx'],'yhgs':res['yhgs'],'yhgroup':res['yhgroup']}
    # 设置token过期时间
    # pay_load里设置pay_load['exp'] = datetime.utcnow()+timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
    
    pay_load['exp'] = datetime.utcnow()+timedelta(days = ACCESS_TOKEN_EXPIRE_DAYS)  #设置过期天数
    access_token = jwt.encode(pay_load,key = SECRET_KEY,algorithm=ALGORITHM) #生成Access token
    #成功，返回resp_200,传递data参数
    return resp_200(data={'access_token':access_token,'token_type':'bearer'})

#校验token，Authorization值
def validToken(Authorization:str = Header(...)):
    try:
        token = Authorization.split(' ')[1]
        pay_load = jwt.decode(token,SECRET_KEY,algorithms=ALGORITHM)
        return pay_load
    except:
        return None

# 查询车票信息
@jianpiao_router.post("/ticket_list", response_model=List[SearchOut])
def ticket_list(params : SearchIn):
    db_user = cpb_crud.get_ticket(params.dict(exclude_unset=True))
    user = SearchOut(**db_user).__dict__
    print(user)
    if not user:
        return resp_400(msg='Not found')
    return resp_200(data=user)

@jianpiao_router.get("/ticket_dayin")
def ticket_dayin(bbkh:str=Query(None,maxngth=20)):
    params = {'cpb.bbkh':bbkh}
    params=DayinbbkhIn(**params)
    print(params)
    res=cpb_crud.select_dayin_bbkh(params.dict(exclude_none=True))
    print(res)
    if not res:
        return resp_400(msg="数据为空")
    return resp_200(data={'items':res})

# #通过报班卡号查询第一个界面
# @jianpiao_router.post("/ticket_bbkh", response_model=List[TicketOut])
# def ticket_bbkh(params : TicketIn):
#     #exclude_unset未传递的值会被忽略
#     db_bbkh = cpb_crud.get_ticket(params.dict(exclude_unset=True))
#     if not db_bbkh:
#         raise HTTPException(status_code=404, detail="Not found")
#     return db_bbkh
